home *** CD-ROM | disk | FTP | other *** search
- /* ThinkDriverGlue.c */
- /*
- * ThinkDriverGlue.c
- * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
- *
- * ThinkDriverGlue.c contains the driver header that
- * connects our driver to the Macintosh O.S. This file
- * contains assembler code that was copied directly from
- * MPWDriverGlue.a. You should refer to MPWDriverGlue.a
- * for an explanation of what is going on. The documentation
- * in this file is primarily intended to explain issues
- * specific to Think C.
- *
- * Note that you must define the project as a code resource
- * of type 'DRVR', id 11.
- *
- * The final Rez operation constructs the driver out of the
- * various pieces. Be sure to use the following options when
- * you set the Think Project Type parameters:
- * Code Resource
- * 'DRVR' Resource Type
- * 11 Resource ID
- * Custom Headers must be selected
- * The file name must be ThinkSampleDriver
- * Also, in the Think C Preferences, be sure to change
- * the Prefix so you do not include <MacHeaders>
- *
- * Unlike the driver support provided with Think C 5.0,
- * you must observe the following (MPW-compatible)
- * restrictions when writing your driver:
- * -- Your driver must not use global or static variables.
- * Instead, your OpenDRVR function must create and
- * initialize the driver control block defined by
- * devCtlEnt->dCtlStorage. Your driver routines
- * must also maintain the dCtlStorage value (locking
- * and unlocking it if you choose to define it as
- * a handle) and CloseDRVR must delete the storage
- * if this is appropriate.
- * -- Your driver MUST be in a single segment. The Think
- * compiler uses A4 references to access the function
- * globals for multi-segmented drivers. A4 is, however,
- * meaningless in our MPW-Think compatible design
- * -- All driver functions return the OSErr value
- * that is to be returned to the caller. Your functions
- * must also store the OSErr value in the ioResult
- * field of the parameter block. It should return +1
- * if the user request has not completed (i.e., the
- * driver was called asychronously and I/O is pending.)
- * -- You can't use the Think Debugger to debug drivers.
- *
- * Author: Martin Minow
- * Apple Computer Inc.
- * Cupertino, CA, USA
- * InterNet: minow@apple.com
- * AppleLink: MINOW
- */
- #include <Errors.h>
- #include <Devices.h>
- #include <THINK.h>
- /*
- * Note: THINK.h defines noQueueBit as a mask, but it must
- * be a number for assembler
- */
- #define noQueueBitNumber 0x09
-
- #define ioBusy (1)
- #define JIODone 0x8FC /* Copied from SysEqu.h */
-
- extern OSErr OpenDRVR(
- CntrlParam *paramBlock,
- DCtlPtr devCtlEnt
- );
- extern OSErr PrimeDRVR(
- CntrlParam *paramBlock,
- DCtlPtr devCtlEnt
- );
- extern OSErr ControlDRVR(
- CntrlParam *paramBlock,
- DCtlPtr devCtlEnt
- );
- extern OSErr StatusDRVR(
- CntrlParam *paramBlock,
- DCtlPtr devCtlEnt
- );
- extern OSErr CloseDRVR(
- CntrlParam *paramBlock,
- DCtlPtr devCtlEnt
- );
-
- void main(void);
- /*
- * Think C links the file containing main at the start
- * of the segment.
- *
- * Note: in order for the following to work, your driver
- * *M*U*S*T* be written as a single segment.
- */
- void
- main(void)
- {
- asm {
- /*
- * These word definitions create the driver prefix.
- */
- dc.w (dNeedLock | dCtlEnable) ; dCtlFlags
- dc.w 0 ; drvrDelay
- dc.w 0 ; drvrEMask
- dc.w 0 ; drvrMenu
- /*
- * These are offsets to the driver glue code.
- */
- dc.w 0x32 ; Open offset
- dc.w 0x36 ; Prime offset
- dc.w 0x3A ; Control offset
- dc.w 0x3E ; Status offset
- dc.w 0x42 ; Close offset
- /*
- * This is a 32 byte string -- it must be identical to the string
- * defined in DTSSampleCSAMDriver.r. Note: it *must* be exactly
- * 32 bytes long for the above offsets to work correctly. Each
- * line (dc.b statement) must have an even number of bytes.
- */
- dc.b 0x0F,'.','S','a','m','p','l','e'
- dc.b ' ','C','a','t','a','l','o','g'
- dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- /*
- * The driver glue handlers. Note: Think C compiles the PEA as an A4-relative
- * operation. If the driver eventually links as a single segment, the linker
- * will change the A4-relative addressing to PC-relative, which is what
- * we need. If you need to support a multi-segment driver, you should use
- * the Think-supplied driver header (define your project as a device driver)
- * and handle compatibility between Think and MPW in some other fashion.
- * Those considerations, however, are beyond the scope of this example.
- */
- bra.s @openGlue
- nop ; For DRVR offset
- bra.s @primeGlue
- nop ; For DRVR offset
- bra.s @controlGlue
- nop ; For DRVR offset
- bra.s @statusGlue
- nop ; For DRVR offset
- closeGlue: pea CloseDRVR
- bra.s @common
- openGlue: pea OpenDRVR ; The function we want to call
- bra.s @common ; Continue at the common code.
- primeGlue: pea PrimeDRVR
- bra.s @common
- controlGlue: pea ControlDRVR
- bra.s @common
- statusGlue: pea StatusDRVR
- /** bra.s @common **/
- common:
- move.l (a7)+,d0 ; Recover the function address
- link a6,#0 ; Establish a stack frame
- movem.l d1-d3/a0-a4,-(a7) ; Save registers
- move.l a1,-(a7) ; Push DCE Ptr on the stack
- move.l a0,-(a7) ; Push ParamBlockPtr on the stack
- move.l d0,a0 ; Get the function to call
- lea main,a4 ; Establish an A4 frame for Think C
- jsr (a0) ; Call the handler
- addq.w #8,a7 ; Clear parameters from stack
- movem.l (a7)+,d1-d3/a0-a4 ; Restore registers
- btst #noQueueBitNumber,IOParam.ioTrap(a0) ; Is noQueueBit set?
- bne.s @exit ; Branch if so
- cmp.w #ioBusy,d0 ; C result "incomplete"?
- beq.s @exit ; Branch if so
- unlk a6 ; I/O complete, clear linkage
- move.l JIODone,-(a7) ; Return via jIODone
- rts ; Completion return
- exit: unlk a6 ; Unlink stack frame for
- rts ; incomplete return
- }
- }
-
-